package factory

import (
	"context"

	"code.byted.org/gopkg/logs/v2/log"

	"code.byted.org/bytertc/whiteboard_server/biz/api/pb"
	v1 "code.byted.org/bytertc/whiteboard_server/biz/api/pb/v1"
	"code.byted.org/bytertc/whiteboard_server/biz/config"
	"code.byted.org/bytertc/whiteboard_server/biz/dal"
	"code.byted.org/bytertc/whiteboard_server/biz/pkg/biz_error"
	"code.byted.org/bytertc/whiteboard_server/biz/service/command"
	"code.byted.org/bytertc/whiteboard_server/biz/service/command/base"
	"code.byted.org/bytertc/whiteboard_server/biz/service/command/modify"
	"code.byted.org/bytertc/whiteboard_server/biz/service/command/query"
	"github.com/pkg/errors"
)

func New(ctx context.Context, boardRepo dal.Repo, cfg config.DynamicConfig, request *v1.OnWireRequest) (c command.Command, err error) {
	cmd := &base.Command{
		Info: base.Info{
			AppId:    request.AppId,
			RoomId:   request.RoomId,
			Operator: request.Operator,
		},
		Repo:   boardRepo,
		Config: cfg,
	}

	msg, err := pb.UnmarshalCommand(request.Command, request.Data)
	if err != nil {
		return nil, biz_error.DecodeError.Wrap(errors.Wrapf(err, "unmarshal %s", request.Command))
	}

	switch request.Command {
	case v1.Command_kGetBoardInfo:
		boardInfo, _ := msg.(*v1.GetBoardInfoRequest)
		return query.NewGetBoardInfoCommand(ctx, cmd, boardInfo.BoardIds), nil
	case v1.Command_kEditing:
		edit, _ := msg.(*v1.EditingRequest)
		return modify.NewEditingCommand(ctx, cmd, edit.Packet)
	case v1.Command_kHeartBeat:
		heartbeat, _ := msg.(*v1.HeartBeatRequest)
		return query.NewHeartbeatCommand(ctx, cmd, heartbeat.BoardId, heartbeat.Version, heartbeat.PageId, heartbeat.MyEditingObjIds), nil
	case v1.Command_kGetActionCount:
		actionCount, _ := msg.(*v1.GetActionCountRequest)
		return query.NewActionCountCommand(ctx, cmd, actionCount.BoardId, actionCount.PageId), nil
	case v1.Command_kGetShapeSnapshot:
		snapshot, _ := msg.(*v1.GetShapeSnapshotRequest)
		return query.NewSnapshotCommand(ctx, cmd, snapshot.Id, snapshot.PageId, snapshot.BoardId, snapshot.ObjIds), nil
	case v1.Command_kCreateBoard:
		createBoard, _ := msg.(*v1.CreateBoardRequest)
		initialPages := createBoard.InitialPages
		for i := 0; i < len(initialPages); i++ {
			log.V1.CtxInfo(ctx, "initial_pages:%#v,ppt_info:%#v", initialPages[i], initialPages[i].PptInfo)
		}

		if createBoard.InitialPage != nil {
			initialPages = []*v1.PageInfo{createBoard.InitialPage}
		}
		var boardName string
		if createBoard.BoardName != nil {
			boardName = *createBoard.BoardName
		}
		return modify.NewCreateBoardCommand(ctx, cmd, createBoard.BoardId, boardName, initialPages, createBoard.PptConfig, createBoard.TaskId, createBoard.TotalSize), nil

	}

	return nil, biz_error.InvalidParam.Wrap(errors.Errorf("unimplemented command %s", request.Command))
}
